/**
 * 
 */
package com.qdairlines.service.file.impl;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import javax.imageio.ImageIO;

import org.apache.commons.lang3.StringUtils;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.StorageClient1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.qdairlines.common.TraceUtil;
import com.qdairlines.service.file.FastDFSClientService;
import com.qdairlines.service.file.FastDFSConnectionPool;

/**
 * @author pangyannan
 * @date 2017年5月15日
 * @company QingDao Airlines
 * @description
 */
@Service
public class FastDFSClientServiceImpl implements FastDFSClientService {
	private static final Logger logger = LoggerFactory
			.getLogger(FastDFSClientService.class);

	@Override
	public String uploadFile(File file, String fileName) {
		if (isNoUploadFileName(fileName)) {
			return null;
		}
		// 获取连接

		StorageClient1 storageClient1 = FastDFSConnectionPool.checkout();

		FileInputStream fis = null;
		try {
			NameValuePair[] meta_list = null; // new NameValuePair[0];
			fis = new FileInputStream(file);
			byte[] file_buff = null;
			if (fis != null) {
				int len = fis.available();
				file_buff = new byte[len];
				fis.read(file_buff);
			}

			// 上传操作
			String fileid = storageClient1.upload_file1(file_buff,
					getFileExt(fileName), meta_list);
			return fileid;
		} catch (Exception e) {
			TraceUtil.error(logger, e);
			return null;
		} finally {
			FastDFSConnectionPool.checkin(storageClient1); // 关闭连接
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					TraceUtil.error(logger, e);
				}
			}
		}
	}

	@Override
	public String uploadFile(InputStream inputStream, String fileName,
			long fileLength) {
		if (isNoUploadFileName(fileName)) {
			return null;
		}
		// 获取连接
		StorageClient1 storageClient1 = FastDFSConnectionPool.checkout();

		try {
			NameValuePair[] meta_list = null; // new NameValuePair[0];
			byte[] fileBuff = getFileBuffer(inputStream, fileLength);

			// 上传操作
			String type = getFileExt(fileName);
			String fileid = storageClient1.upload_file1(fileBuff, type,
					meta_list);
			return fileid;
		} catch (Exception e) {
			TraceUtil.error(logger, e);
			return null;
		} finally {
			FastDFSConnectionPool.checkin(storageClient1); // 关闭连接
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					TraceUtil.error(logger, e);
				}
			}
		}
	}

	@Override
	public String uploadFile(MultipartFile multipartFile) {
		try {
			InputStream inputStream = multipartFile.getInputStream();
			long fileLength = multipartFile.getSize();
			String fileName = multipartFile.getOriginalFilename();
			return uploadFile(inputStream, fileName, fileLength);
		} catch (Exception e) {
			TraceUtil.error(logger, e);
			return null;
		}
	}

	@Override
	public int deleteFile(String fileId) {
		// 获取连接
		StorageClient1 storageClient1 = FastDFSConnectionPool.checkout();

		try {
			int result = storageClient1.delete_file1(fileId);
			return result;
		} catch (Exception e) {
			TraceUtil.error(logger, e);
			return 0;
		} finally {
			FastDFSConnectionPool.checkin(storageClient1); // 关闭连接
		}
	}

	@Override
	public InputStream downloadFile(String fileId) {
		// 获取连接
		StorageClient1 storageClient1 = FastDFSConnectionPool.checkout();

		try {
			byte[] bytes = storageClient1.download_file1(fileId);
			InputStream inputStream = new ByteArrayInputStream(bytes);
			return inputStream;
		} catch (Exception e) {
			TraceUtil.error(logger, e);
			return null;
		} finally {
			FastDFSConnectionPool.checkin(storageClient1); // 关闭连接
		}
	}

	@Override
	public byte[] downloadFileTobyte(String fileId) {
		// 获取连接
		StorageClient1 storageClient1 = FastDFSConnectionPool.checkout();

		try {
			byte[] b = storageClient1.download_file1(fileId);
			return b;
		} catch (Exception e) {
			TraceUtil.error(logger, e);
			return null;
		} finally {
			FastDFSConnectionPool.checkin(storageClient1); // 关闭连接
		}
	}

	@Override
	public ResponseEntity<byte[]> downloadFile(String fileId, String fileName) {
		byte[] filedata = this.downloadFileTobyte(fileId);

		// 设置请求头内容,告诉浏览器代开下载窗口
		HttpHeaders headers = new HttpHeaders();
		headers.setContentDispositionFormData("attachment", fileName);
		headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
		return new ResponseEntity<byte[]>(filedata, headers, HttpStatus.OK);
	}

	@Override
	public ResponseEntity<byte[]> downloadFileTranscoding(String fileId,
			String fileName) {
		byte[] filedata = this.downloadFileTobyte(fileId);

		// 处理显示中文文件名的问题
		String downloadFileName = "";
		try {
			downloadFileName = new String(fileName.getBytes("utf-8"),
					"ISO-8859-1");
		} catch (UnsupportedEncodingException e) {
			TraceUtil.error(logger, e);
		}

		// 设置请求头内容,告诉浏览器代开下载窗口
		HttpHeaders headers = new HttpHeaders();
		headers.setContentDispositionFormData("attachment", downloadFileName);
		headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
		return new ResponseEntity<byte[]>(filedata, headers, HttpStatus.OK);
	}

	@Override
	public ResponseEntity<byte[]> getSmallImage(String fileId, String fileName,
			int maxLength) {
		String imgType = getFileExt(fileName).toLowerCase();
		if (!("jpg".equals(imgType) || "png".equals(imgType)
				|| "jpeg".equals(imgType) || "bmp".equals(imgType)
				|| "gif".equals(imgType) || "tiff".equals(imgType))) {
			return null;
		}

		byte[] filedata = this.downloadFileTobyte(fileId);
		ByteArrayInputStream in = new ByteArrayInputStream(filedata); // 将byte作为输入流；
		BufferedImage image = null;
		try {
			image = ImageIO.read(in);
		} catch (IOException e1) {
			e1.printStackTrace();
		}

		int old_w = image.getWidth(); // 得到源图宽
		int old_h = image.getHeight(); // 得到源图长
		if (old_w > maxLength || old_h > maxLength) {
			int new_w = 0; // 新图的宽
			int new_h = 0; // 新图的长

			BufferedImage tempImg = new BufferedImage(old_w, old_h,
					BufferedImage.TYPE_INT_RGB);
			Graphics2D g = tempImg.createGraphics();

			g.setColor(Color.white);
			// 从原图上取颜色绘制新图
			g.fillRect(0, 0, old_w, old_h);
			g.drawImage(image, 0, 0, old_w, old_h, Color.white, null);
			g.dispose();
			// 根据图片尺寸压缩比得到新图的尺寸
			if (old_w > old_h) {
				// 图片要缩放的比例
				new_w = maxLength;
				new_h = (int) Math.round(old_h * ((float) maxLength / old_w));
			} else {
				new_w = (int) Math.round(old_w * ((float) maxLength / old_h));
				new_h = maxLength;
			}

			BufferedImage newImg = new BufferedImage(new_w, new_h,
					BufferedImage.TYPE_INT_RGB);
			newImg.getGraphics()
					.drawImage(
							tempImg.getScaledInstance(new_w, new_h,
									Image.SCALE_SMOOTH), 0, 0, null);

			ByteArrayOutputStream os = new ByteArrayOutputStream();// 新建流。

			try {
				ImageIO.write(newImg, getFileExt(fileName), os); // 利用ImageIO类提供的write方法，将
																	// newImg
																	// 图片的数据模式写入流。
			} catch (IOException e) {
				TraceUtil.error(logger, e);
			}

			byte[] b = os.toByteArray();// 从流中获取数据数组。

			// 处理显示中文文件名的问题
			String downloadFileName = "";
			try {
				downloadFileName = new String(fileName.getBytes("utf-8"),
						"ISO-8859-1");
			} catch (UnsupportedEncodingException e) {
				TraceUtil.error(logger, e);
			}

			// 设置请求头内容,告诉浏览器代开下载窗口
			HttpHeaders headers = new HttpHeaders();
			headers.setContentDispositionFormData("attachment",
					downloadFileName);
			headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

			return new ResponseEntity<byte[]>(b, headers, HttpStatus.CREATED);
		} else {
			return downloadFileTranscoding(fileId, fileName);
		}

	}

	/**
	 * 将输入流转换为字节
	 * 
	 * @param inputStream
	 * @param fileLength
	 * @return
	 */
	private static byte[] getFileBuffer(InputStream inputStream, long fileLength) { // long
																					// fileLength
		byte[] buffer = new byte[256 * 1024];
		byte[] fileBuffer = new byte[(int) fileLength];

		int count = 0;
		int length = 0;

		try {
			while ((length = inputStream.read(buffer)) != -1) {
				for (int i = 0; i < length; ++i) {
					fileBuffer[count + i] = buffer[i];
				}
				count += length;
			}
		} catch (IOException e) {
			TraceUtil.error(logger, e);
		}
		return fileBuffer;
	}

	/**
	 * 获取文件后缀名（不带点）.
	 * 
	 * @return 如："jpg" or "".
	 */
	private String getFileExt(String fileName) {
		if (StringUtils.isBlank(fileName) || !fileName.contains(".")) {
			return "";
		} else {
			return fileName.substring(fileName.lastIndexOf(".") + 1); // 不带最后的点
		}
	}

	/**
	 * 判断是否是禁止上传的文件类型，如果是禁止上传的文件，则返回true
	 * 
	 * @param fileName
	 * @return
	 */
	private boolean isNoUploadFileName(String fileName) {
		String[] noUploadFiles = { "exe", "sh", "bat", "app", "cmd", "com",
				"cpl", "dll", "hta", "htm", "html", "htt", "inf", "jse", "msi",
				"msp", "mst", "pif", "prf", "prg", "reg", "scf", "scr", "sct",
				"shb", "shs", "url", "vbe", "vbs", "vsmacros", "ws", "wsc",
				"wsf", "wsh" };
		String fileType = StringUtils.lowerCase(getFileExt(fileName));
		for (String str : noUploadFiles) {
			if (StringUtils.equals(str, fileType)) {
				return true;
			}
		}
		return false;
	}
}
